package com.zxg.zbc.web.common.util;

import static com.alibaba.citrus.springext.util.SpringExtUtil.attributesToProperties;
import static com.alibaba.citrus.turbine.util.TurbineUtil.getTurbineRunData;
import static com.alibaba.citrus.util.StringUtil.trimToNull;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;

import com.alibaba.citrus.service.pipeline.PipelineContext;
import com.alibaba.citrus.service.pipeline.support.AbstractValveDefinitionParser;
import com.alibaba.citrus.turbine.pipeline.valve.AbstractInputOutputValve;
import com.alibaba.citrus.turbine.support.TurbineRunDataImpl;
import com.alibaba.fastjson.JSON;

/**
 * 
 * @author HangDing
 *
 *         2014年1月1日
 */
public class RenderResultAsJsonValve extends AbstractInputOutputValve {
  private static final String DEFAULT_CONTENT_TYPE            = "application/json";
  private static final String DEFAULT_JAVASCRIPT_VARIABLE     = null;
  private static final String DEFAULT_JAVASCRIPT_CONTENT_TYPE = "application/javascript";

  @Autowired
  private HttpServletRequest  request;

  @Autowired
  private HttpServletResponse response;

  private String              contentType;
  private String              javascriptVariable;
  private String              javascriptContentType;

  public String getContentType() {
    return contentType == null ? DEFAULT_CONTENT_TYPE : contentType;
  }

  public void setContentType(String contentType) {
    this.contentType = trimToNull(contentType);
  }

  public String getJavascriptVariable() {
    return javascriptVariable == null ? DEFAULT_JAVASCRIPT_VARIABLE : javascriptVariable;
  }

  public void setJavascriptVariable(String javascriptVariable) {
    this.javascriptVariable = trimToNull(javascriptVariable);
  }

  public String getJavascriptContentType() {
    return javascriptContentType == null ? DEFAULT_JAVASCRIPT_CONTENT_TYPE : javascriptContentType;
  }

  public void setJavascriptContentType(String javascriptContentType) {
    this.javascriptContentType = trimToNull(javascriptContentType);
  }

  public void invoke(PipelineContext pipelineContext) throws Exception {
    TurbineRunDataImpl rundata = (TurbineRunDataImpl) getTurbineRunData(request);

    if (!rundata.isRedirected()) {
      Object resultObject = consumeInputValue(pipelineContext);

      if (resultObject == null) {
        resultObject = rundata.getContext(null).get("result");
        if (resultObject == null)
          return;
      }

      String javascriptVariable = getJavascriptVariable();
      boolean outputAsJson = javascriptVariable == null;

      if (outputAsJson) {
        // output as json
        response.setContentType(getContentType());
      } else {
        // output as javascript
        response.setContentType(getJavascriptContentType());
      }

      PrintWriter out = response.getWriter();
      String jsonResult = null;
      try {
        jsonResult = JSON.toJSONString(resultObject);
      } catch (Exception e) {
        jsonResult = "error parse " + e.getMessage();
      }
      if (outputAsJson) {
        out.print(jsonResult);
      } else {
        out.print("var ");
        out.print(javascriptVariable);
        out.print(" = ");
        out.print(jsonResult);
        out.print(";");
      }
    }

    pipelineContext.invokeNext();
  }

  public static class DefinitionParser extends AbstractValveDefinitionParser<RenderResultAsJsonValve> {
    @Override
    protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
      attributesToProperties(element, builder, "input", "contentType", "javascriptVariable", "javascriptContentType");
    }
  }
}
